#include "Drawable.h"
#include <utils\ResourceManager.h>
#include <main/MainConstants.h>

Drawable::Drawable(const std::string& id, 
                   Entity* entity, 
                   const int* w,
                   const int* h) 
	: mAllowPhysics(entity != nullptr), enableConstantVelocity(false), drawOnTop(false)
{
	texture.mTexture = Globals::gResourceManager->getTexture(id);
	int width;
	int height;

    if (!w || !h) {
        getTextureSize(width, height);
    } else {
        width = *w;
        height = *h;
    }

    if (mAllowPhysics) {  
        entity->mDrawable = this;
        body = Globals::gCollisionManager->createCollider(width, height, entity->pisycs, entity->staticObject);
        body->SetUserData(entity);   
        Globals::gGameLoop->updateMe(this);
    }

    updatePosition(0, 0);	
}

void Drawable::getTextureSize(int& w, int& h) {
    SDL_QueryTexture(texture.mTexture, 0, 0, &w, &h);
}

void Drawable::draw() {
	drawTextures(&worldSpace, &texture, 1);
}

void Drawable::setVelocity(b2Vec2 vel) {
	body->SetLinearVelocity(vel);
}

void Drawable::setConstantVelocity(b2Vec2 vel) {
	body->SetLinearVelocity(vel);
	enableConstantVelocity = true;
}

void Drawable::update() {
	// If we are here it means we are moved by pysics so update position based on that
	const b2Vec2 pos = body->GetPosition();
	
	worldSpace.mOrientation = -body->GetAngle();
	worldSpace.mCenterPosX = pos.x * METER_TO_PIXEL;
	worldSpace.mCenterPosY = pos.y * METER_TO_PIXEL;

	if(enableConstantVelocity) {
		b2Vec2 dir = body->GetLinearVelocity();
        dir.Normalize();
		body->SetLinearVelocity(1000 * dir);
	}
}

Drawable::~Drawable() {
    if (mAllowPhysics) {
	    Globals::gGameLoop->removeMe(this);
		Globals::gCollisionManager->destroy(body);
    }
}

void Drawable::updateTexture(SDL_Texture* newTexture) {
	texture.mTexture = newTexture;
}

void Drawable::updatePosition(float x, float y, float orientation) {
	worldSpace.mCenterPosX = x;
	worldSpace.mCenterPosY = y;
	worldSpace.mOrientation = orientation;
		
    if (mAllowPhysics) {
		b2Vec2 position(x * PIXEL_TO_METER, y * PIXEL_TO_METER);
        body->SetTransform(position, -orientation);
    }
}

void Drawable::updateOrientation(const float orientation) {
    worldSpace.mOrientation = orientation;

    if (mAllowPhysics) {
        b2Vec2 position(worldSpace.mCenterPosX * PIXEL_TO_METER, worldSpace.mCenterPosY * PIXEL_TO_METER);
        body->SetTransform(position, orientation);
    }
}

const StaticData& Drawable::getPosition() {
	return worldSpace;
}
